package com.gateway.router.resilience4j.handler;

import com.gateway.common.dto.convert.rule.Resilience4JHandle;
import com.gateway.common.dto.route.FilterData;
import com.gateway.common.utils.JsonUtils;
import com.gateway.router.base.cache.CommonHandleCache;
import com.gateway.router.base.handler.RouteFilterDataHandler;
import com.gateway.router.base.utils.CacheKeyUtils;
import com.gateway.router.base.utils.RouterBeanHolder;
import com.gateway.router.resilience4j.builder.Resilience4JBuilder;
import com.gateway.router.resilience4j.factory.Resilience4JRegistryFactory;
import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig;
import io.github.resilience4j.timelimiter.TimeLimiterConfig;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.cloud.gateway.filter.factory.SpringCloudCircuitBreakerFilterFactory;

import java.util.Optional;
import java.util.function.Supplier;

/**
 * @program: api-gateway
 * @description:
 * @author: YuKai Fan
 * @create: 2025/2/24 19:42
 **/
public class Resilience4JRouterFilterHandler implements RouteFilterDataHandler {
    public static final Supplier<CommonHandleCache<String, Resilience4JHandle>> CACHED_HANDLE = new RouterBeanHolder<>(CommonHandleCache::new);

    @Override
    public void handle(FilterData filterData) {
        String key = CacheKeyUtils.INST.getKey(filterData);
        Resilience4JRegistryFactory.remove(key);
        Optional.ofNullable(filterData.getHandle())
                .ifPresent(handle -> {
                    Resilience4JHandle resilience4JHandle = JsonUtils.stringToBean(handle, Resilience4JHandle.class);
                    assert resilience4JHandle != null;
                    Pair<CircuitBreakerConfig, TimeLimiterConfig> pair = Resilience4JBuilder.build(resilience4JHandle);
                    Resilience4JRegistryFactory.addConfig(key, pair.getLeft());
                    Resilience4JRegistryFactory.addConfig(key, pair.getRight());
                });
    }

    @Override
    public void remove(FilterData filterData) {
        String key = CacheKeyUtils.INST.getKey(filterData);
        Resilience4JRegistryFactory.remove(key);
        Optional.ofNullable(filterData.getHandle()).ifPresent(handle -> CACHED_HANDLE.get().removeHandle(key));
    }

    @Override
    public String filterName() {
        return SpringCloudCircuitBreakerFilterFactory.NAME;
    }
}
